#include <func.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <jwt.h>
#include "Crypto.h"

char secret_key[] = "CloudDisk.SECRET_KEY";
const unsigned char key[33] = "CloudDisk.KEY";  
const unsigned char iv[17] = "CloudDisk.IV";

int aes256_encrypt(const unsigned char* plaintext, int plaintext_len,
                   unsigned char* ciphertext)
{
    EVP_CIPHER_CTX* context = EVP_CIPHER_CTX_new();     // 创建上下
    // 初始化 AES-256-CBC 加密
    EVP_EncryptInit_ex(context, EVP_aes_256_cbc(), NULL, key, iv);

    // 加密
    int len, ciphertext_len;
    EVP_EncryptUpdate(context, ciphertext, &len, plaintext, plaintext_len);
    ciphertext_len = len;
    // 处理填充部分
    EVP_EncryptFinal_ex(context, ciphertext + len, &len);
    ciphertext_len += len;

    EVP_CIPHER_CTX_free(context);
    return ciphertext_len;
}

int aes256_decrypt(const unsigned char* ciphertext, int ciphertext_len,
                   unsigned char* plaintext)
{
    EVP_CIPHER_CTX* context = EVP_CIPHER_CTX_new(); // 创建上下文

    int len, plaintext_len;
    // 初始化 AES_256_CBC 解密
    EVP_DecryptInit_ex(context, EVP_aes_256_cbc(), NULL, key, iv);
    // 解密
    EVP_DecryptUpdate(context, plaintext, &len, ciphertext, ciphertext_len);
    plaintext_len = len;

    // 处理填充部分
    EVP_DecryptFinal_ex(context, plaintext + len, &len);
    plaintext_len += len;

    EVP_CIPHER_CTX_free(context);
    return plaintext_len;
}

void generate_salt(char* salt, int n)
{
    static char alpha[] = "abcdefghijklmnopqrstuvwxyz";
    for (int i = 0; i < n; i++) {
        salt[i] = alpha[rand() % 26];
    }
}

// 在 OpenSSL 3.0 中，SHA256_Init(), SHA256_Update(), SHA256_Final()
// 等 API 已被废弃，不推荐使用
/* void sha256_passwd2(const char* salt, const char* passwd, char* output) */
/* { */
/*     SHA256_CTX context; */
/*     SHA256_Init(&context); */
/*     SHA256_Update(&context, salt, strlen(salt)); */
/*     SHA256_Update(&context, passwd, strlen(passwd)); */
/*     unsigned char data[SHA256_DIGEST_LENGTH]; */
/*     SHA256_Final(data, &context); */
/*     for(int i = 0; i < SHA256_DIGEST_LENGTH; i++) { */
/*         sprintf(output + 2 * i, "%02x", data[i]); */
/*     } */
/* } */

// OpenSSL 3.0 及更新版本推荐使用 EVP(Envelope) 接口 
void sha256_passwd(const char* salt, const char* passwd, char* output)
{
    EVP_MD_CTX* context = EVP_MD_CTX_new(); // 创建 EVP 上下文

    // 初始化上下文，采用 sha256 哈希算法
    EVP_DigestInit_ex(context, EVP_sha256(), NULL);
    // 更新上下文
    EVP_DigestUpdate(context, salt, strlen(salt));
    EVP_DigestUpdate(context, passwd, strlen(passwd));
    // 计算哈希值
    unsigned char hash[EVP_MAX_MD_SIZE];    // 最大哈希长度
    unsigned int len = 0;                   // 用来接收实际哈希长度
    EVP_DigestFinal(context, hash, &len);
    // 转换成十六进制字符，存储到output中
    for(unsigned i = 0; i < len; i++) {
        sprintf(output + 2 * i, "%02x", hash[i]);
    }

    EVP_MD_CTX_free(context);               // 释放上下文
}

#ifdef TEST_CRYPTO
int main(int argc, char* argv[]) 
{
    srand(time(NULL));
    char username[26];
    char passwd[26];
    char confirm[26];
    printf("用户名: ");
    scanf("%s", username);
    printf("密码: ");
    scanf("%s", passwd);

    printf("确认密码: ");
    scanf("%s", confirm);

    if (strcmp(passwd, confirm) != 0) {
        printf("密码不一致, 请重新输入!\n");
        return 0;
    }

    // 用户名, 盐值, 密码的哈希值...
    char salt[9] = "";
    generate_salt(salt, 8);
    printf("salt: %s\n", salt);
    char sha256sum[65] = "";
    sha256_passwd(salt, passwd, sha256sum);
    printf("sha256sum: %s\n", sha256sum);

    return 0;
}
#endif
